package com.cjz;

import org.junit.Assert;
import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;

import rx.Observable;
import rx.observers.TestSubscriber;
import rx.schedulers.TestScheduler;

/**
 * 介绍RxJava单元测试方法
 */
public class TestDemo {


    /**
     * 演示原始案例
     */
    @Test
    public void demo1() {

        List<Long> result = new ArrayList<>();

        Observable.interval(1, TimeUnit.SECONDS)
                .take(3)
                .subscribe(
                        result::add,
                        e -> System.out.println(e.getMessage()),
                        () -> System.out.println("completed")
                );

        try {
            Thread.sleep(5_000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        result.forEach(System.out::println);
    }

    /**
     * 对测试case的改进, 方案1: 将Observable改造成阻塞式
     */
    @Test
    public void demo2(){
        List<Long> result = new ArrayList<>();
        Observable.interval(1, TimeUnit.SECONDS)
                .take(3)
                .toBlocking()
                .subscribe(
                        result::add,
                        e -> System.out.println(e.getMessage()),
                        () -> System.out.println("completed")
                );
        result.forEach(System.out::println);
    }

    /**
     * 如果每个测试单元都需要3秒...继续改进, 方案2: 使用TestScheduler 操控时间!
     */
    @Test
    public void demo3(){
        List<Long> result = new ArrayList<>();
        TestScheduler testScheduler = new TestScheduler();
        Observable.interval(1, TimeUnit.SECONDS, testScheduler)
                .take(3)
                .subscribe(
                        result::add,
                        e -> System.out.println(e.getMessage()),
                        () -> System.out.println("completed")
                );

        Assert.assertTrue(result.isEmpty());
        testScheduler.advanceTimeBy(5, TimeUnit.SECONDS);
        Assert.assertTrue(!result.isEmpty());
    }

    /**
     * 以上两个例子,关注结果, 如何关注Observable本身?,,,,引入TestSubscriber
     */
    @Test
    public void demo4() {

        TestScheduler testScheduler = new TestScheduler();
        TestSubscriber<Long> tse = new TestSubscriber<>();

        Observable.interval(1, TimeUnit.SECONDS,testScheduler)
                .take(3)
                .subscribe(tse);

        tse.assertNotCompleted();
        testScheduler.advanceTimeBy(5, TimeUnit.SECONDS);
        tse.assertCompleted();
        tse.assertValueCount(3);

        List<Long> expected = Arrays.asList(0L,1L,2L);
        tse.assertReceivedOnNext(expected);
    }

}
